package com.topvision.idcard;

import android.content.Context;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.os.Build;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.ImageView;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;


public class CameraView extends SurfaceView implements SurfaceHolder.Callback, Camera.AutoFocusCallback {

    private static final String TAG = "CameraView";
    private SurfaceHolder mHolder;
    private Camera mCamera;
    Context context;
    Parameters parameters;

    public CameraView(Context context) {
        super(context);
        mHolder = getHolder();
        mHolder.addCallback(this);
        mHolder.setKeepScreenOn(true);
        this.context = context;
    }

    /**
     * 获取照相机对象
     *
     * @param @return
     * @return Camera
     * @throws
     * @Title: getCameraInstance
     * @Description:
     */
    public Camera getCameraInstance() {
        if (mCamera == null) {
            try {
                mCamera = Camera.open();
                setCameraParameters(mCamera);
            } catch (Exception e) {
                Log.d(TAG, "camera is not available");
                e.printStackTrace();

            }

        }

        return mCamera;
    }

    public void surfaceCreated(SurfaceHolder holder) {
        mCamera = getCameraInstance();

        try {
            if (mCamera != null) {
                mCamera.setPreviewDisplay(holder);
                mCamera.startPreview();
                CameraActivity.safeToTakePicture = true;
            }
        } catch (IOException e) {
            Log.d(TAG, "Error setting camera preview: " + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 判断是否支持camera的参数
     * create at 2017/3/6 17:20
     */
    public static boolean isSupported(String value, List<String> supported) {
        return supported == null ? false : supported.indexOf(value) >= 0;
    }

    /**
     * 判断当前设备是否为爱普生系列
     * create at if 15:53
     */
    public static boolean isBtDevice() {
        String device_model = Build.MODEL;
        if (device_model.contains("EMBT")) {
            return true;
        }
        return false;
    }

    /**
     * 设置Camera参数
     *
     * @param @param camera
     * @return void
     * @throws
     * @Title: setCameraParameters
     * @Description:
     */
    private void setCameraParameters(Camera camera) {
        parameters = camera.getParameters();
        parameters.setPreviewSize(1280,720);
        parameters.setPictureSize(1280, 720);
        if (Build.VERSION.SDK_INT >= 21 && !isBtDevice()) {
            if (isSupported(Parameters.FOCUS_MODE_CONTINUOUS_VIDEO, parameters.getSupportedFocusModes())) {
                parameters
                        .setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
            }
        } else {
            if (isSupported(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE, parameters.getSupportedFocusModes())) {
                parameters
                        .setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
            }
        }
        parameters.setPictureFormat(PixelFormat.JPEG); // 设置图片格式
        parameters.setJpegQuality(95); // 设置照片质量
        camera.setParameters(parameters);
    }


    public void surfaceDestroyed(SurfaceHolder holder) {
        if (mCamera != null) {
            mHolder.removeCallback(this);
            mCamera.setPreviewCallback(null);
            mCamera.stopPreview();
            mCamera.release();
            mCamera = null;
            CameraActivity.safeToTakePicture = false;
        }


    }

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        System.out.println("surfaceChanged");
    }

    /**
     * 释放摄像头
     *
     * @param
     * @return void
     * @throws
     * @Title: freeCameraResource
     * @Description:
     */
    public void freeCameraResource() {
        if (mCamera != null) {
            mCamera.setPreviewCallback(null);
            mCamera.stopPreview();
            mCamera.lock();
            mCamera.release();
            mCamera = null;

        }
    }

    public Parameters getParameters() {
        return parameters;
    }

    public void setParameters(Parameters parameters) {
        this.parameters = parameters;
    }


    boolean flashFlag = false;

    /**
     * 打开闪光灯
     * create at 2017/1/11 10:24
     */
    public boolean openFlashLight() {
        try {
            mCamera.stopPreview();
            parameters.setFlashMode(Parameters.FLASH_MODE_TORCH);
            mCamera.setParameters(parameters);
            mCamera.startPreview();
            flashFlag = true;
        } catch (Exception e) {
            e.printStackTrace();
            flashFlag = false;
        }
        return flashFlag;
    }

    /**
     * 关闭闪光灯
     * create at 2017/1/11 10:35
     */
    public void closeFlashLight() {
        if (flashFlag) {
            try {
                mCamera.stopPreview();
                parameters.setFlashMode(Parameters.FLASH_MODE_OFF);
                mCamera.setParameters(parameters);
                mCamera.startPreview();
                flashFlag = false;
            } catch (Exception e) {
                e.printStackTrace();
                flashFlag = true;
            }

        }

    }

    public boolean isFlashFlag() {
        return flashFlag;
    }

    public void setFlashFlag(boolean flashFlag) {
        this.flashFlag = flashFlag;
    }

    public void focusOnTouch() {
        Rect focusRect = calculateTapArea(250, 200, 1f);
        Rect meteringRect = calculateTapArea(250, 200, 1.5f);

        Parameters parameters = mCamera.getParameters();
        parameters.setFocusMode(Parameters.FOCUS_MODE_AUTO);

        if (parameters.getMaxNumFocusAreas() > 0) {
            List<Camera.Area> focusAreas = new ArrayList<Camera.Area>();
            focusAreas.add(new Camera.Area(focusRect, 1000));

            parameters.setFocusAreas(focusAreas);
        }

        if (parameters.getMaxNumMeteringAreas() > 0) {
            List<Camera.Area> meteringAreas = new ArrayList<Camera.Area>();
            meteringAreas.add(new Camera.Area(meteringRect, 1000));

            parameters.setMeteringAreas(meteringAreas);
        }
        mCamera.setParameters(parameters);
        mCamera.autoFocus(this);
    }

    private Rect calculateTapArea(float x, float y, float coefficient) {
        float focusAreaSize = 300;
        int areaSize = Float.valueOf(focusAreaSize * coefficient).intValue();

        int centerX = (int) (x / getResolution().width * 2000 - 1000);
        int centerY = (int) (y / getResolution().height * 2000 - 1000);

        int left = clamp(centerX - areaSize / 2, -1000, 1000);
        int right = clamp(left + areaSize, -1000, 1000);
        int top = clamp(centerY - areaSize / 2, -1000, 1000);
        int bottom = clamp(top + areaSize, -1000, 1000);

        return new Rect(left, top, right, bottom);
    }

    private int clamp(int x, int min, int max) {
        if (x > max) {
            return max;
        }
        if (x < min) {
            return min;
        }
        return x;
    }

    public Camera.Size getResolution() {
        Parameters params = mCamera.getParameters();
        Camera.Size s = params.getPreviewSize();
        return s;
    }

    //定点对焦的代码
    public void pointFocus(ImageView albumIv) {
        mCamera.cancelAutoFocus();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
            focusOnTouch();
        }
    }

    @Override
    public void onAutoFocus(boolean success, Camera camera) {
//        if (success) {
        //无论对焦都拍照
//        mCamera.takePicture(null, null, new TakePhotoCallback(context));
        //}
    }

    //Test start
    private void test() {
        // Set picture size.
        // The logic here is different from the logic in still-mode camera.
        // There we determine the preview size based on the picture size, but
        // here we determine the picture size based on the preview size.
//        List<Camera.Size> supported = parameters.getSupportedPictureSizes();
//        Camera.Size optimalSize = CameraUtil.getOptimalVideoSnapshotPictureSize(supported,
//                (double) mDesiredPreviewWidth / mDesiredPreviewHeight);
//        Camera.Size original = parameters.getPictureSize();
//        if (!original.equals(optimalSize)) {
//            parameters.setPictureSize(optimalSize.width, optimalSize.height);
//        }
    }


}
